package appClientModule;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

@SuppressWarnings("serial")
public class TrainerD extends JDialog {
	private final JLabel alphaLabel = new JLabel("Alpha (step size)");
	private final JLabel discountLabel = new JLabel("Discount");
	private final JLabel greedyLabel = new JLabel("Greedy %");
	private final JLabel trainingLabel = new JLabel("Number of games to train");
	private final JTextField alphaField = new JTextField("0.01");
	private final JTextField discountField = new JTextField("0.99");
	private final JTextField greedyField = new JTextField("80", 3);
	private final JTextField trainingField = new JTextField("10000");
	private final JTextArea reportField = new JTextArea();
	private final JButton okButton = new JButton("Train");
	private final JButton cancelButton = new JButton("Cancel");

	private double alpha;
	private double discount;
	private double greedy;
	private int training;
	private ReinforcementLearningAI ai = new ReinforcementLearningAI(0.01,
			0.99, 80.0);
	private String report;

	public TrainerD(JFrame parent) {
		super(parent, "Trainer", true);
		setupListeners();
		layoutComponents();
	}

	private void setupListeners() {
		okButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				if (okButton.getText().equals("Train")) {
					setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
					try {
						if (validateInputs()) {
							createTrainer();
							okButton.setText("OK");
							reportField.setText(report);
							pack();
						}
					} finally {
						setCursor(Cursor.getDefaultCursor());
					}
				} else {
					setVisible(false);
					dispose();
				}
			}

		});

		cancelButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				setVisible(false);
				dispose();
			}

		});
	}

	private void layoutComponents() {
		setLayout(new GridBagLayout());
		add(alphaLabel, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0,
				GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH,
				new Insets(5, 5, 5, 5), 0, 0));
		add(alphaField, new GridBagConstraints(1, 0, 1, 1, 1.0, 1.0,
				GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH,
				new Insets(5, 5, 5, 5), 0, 0));
		add(discountLabel, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0,
				GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH,
				new Insets(5, 5, 5, 5), 0, 0));
		add(discountField, new GridBagConstraints(1, 1, 1, 1, 1.0, 1.0,
				GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH,
				new Insets(5, 5, 5, 5), 0, 0));
		add(greedyLabel, new GridBagConstraints(0, 2, 1, 1, 1.0, 1.0,
				GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH,
				new Insets(5, 5, 5, 5), 0, 0));
		add(greedyField, new GridBagConstraints(1, 2, 1, 1, 1.0, 1.0,
				GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH,
				new Insets(5, 0, 5, 5), 0, 0));
		add(trainingLabel, new GridBagConstraints(0, 3, 1, 1, 1.0, 1.0,
				GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH,
				new Insets(0, 5, 5, 5), 0, 0));
		add(trainingField, new GridBagConstraints(1, 3, 1, 1, 1.0, 1.0,
				GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH,
				new Insets(0, 0, 5, 5), 0, 0));
		add(new JScrollPane(reportField), new GridBagConstraints(0, 4, 2, 1,
				1.0, 2.0, GridBagConstraints.NORTHWEST,
				GridBagConstraints.BOTH, new Insets(0, 5, 5, 5), 0, 0));
		add(okButton, new GridBagConstraints(0, 5, 1, 1, 1.0, 1.0,
				GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH,
				new Insets(0, 5, 5, 5), 0, 0));
		add(cancelButton, new GridBagConstraints(1, 5, 1, 1, 1.0, 1.0,
				GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH,
				new Insets(0, 0, 5, 5), 0, 0));
		pack();
	}

	private boolean validateInputs() {
		try {
			alpha = Double.parseDouble(alphaField.getText());
			if (alpha > 1) {
				return false;
			}
			
			discount = Double.parseDouble(discountField.getText());
			if (discount > 1) {
				return false;
			}
			
			greedy = Double.parseDouble(greedyField.getText());
			if (greedy < 0 || greedy > 100) {
				return false;
			}

			training = Integer.parseInt(trainingField.getText());
			if (training < 0) {
				return false;
			}

			return true;
		} catch (NumberFormatException e) {
			return false;
		}
	}

	private void createTrainer() {
		Trainer trainer = new Trainer(alpha, discount, greedy, training);
		ai = trainer.trainReinforcementLearner();
		report = trainer.getTrainingReport();
	}

	public ReinforcementLearningAI getTrainedReinforcementLearner() {
		return ai;
	}
}
